#include "CLinkRoomCommand.h"
#include "CUserInterface.h"
#include "CLevelEditor.h"
#include "DoUndoCommands.h"
#include "CDeleteCommand.h"
#include "ISceneManager.h"
#include "ISceneNode.h"
#include "CSceneObject.h"


extern CGlobals* g;
extern CUserInterface* ui;
extern CLevelEditor* editor;

CLinkRoomCommand::CLinkRoomCommand (int fromId, int toId, int fromLinkIndex, int toLinkIndex)
{
	m_fromId = fromId;
	m_toId = toId;
	m_fromLinkIndex = fromLinkIndex;
	m_toLinkIndex = toLinkIndex;

	CSceneObject *pObjFrom = editor->getSceneObjectFromID(m_fromId);
	m_fromOldRoomID = pObjFrom->m_roomIDLinks[fromLinkIndex];
	m_fromOldDoorID = pObjFrom->m_linkDoorID[fromLinkIndex];
	m_fromOldLinkIndex = pObjFrom->m_linkIndexLinks[fromLinkIndex];

	if (m_toId != -1)
	{
		CSceneObject *pObjTo = editor->getSceneObjectFromID(m_toId);
		m_toOldRoomID = pObjTo->m_roomIDLinks[toLinkIndex];
		m_toOldDoorID = pObjTo->m_linkDoorID[toLinkIndex];
		m_toOldLinkIndex = pObjTo->m_linkIndexLinks[toLinkIndex];
	}
	
	setDescription(stringw(L"update room links"));

	m_pDelCmd1 = NULL;
	m_pDelCmd2 = NULL;
}

CLinkRoomCommand::~CLinkRoomCommand()
{
	if (m_pDelCmd1) m_pDelCmd1->drop();
	if (m_pDelCmd2) m_pDelCmd2->drop();
}

void CLinkRoomCommand::redo ()
{
	if (m_fromOldRoomID == m_toId && m_fromOldLinkIndex == m_toLinkIndex) 
	{
		return;
	}

	CSceneObject *pObjFrom = editor->getSceneObjectFromID(m_fromId);
	pObjFrom->m_roomIDLinks[m_fromLinkIndex] = m_toId;
	pObjFrom->m_linkIndexLinks[m_fromLinkIndex] = m_toLinkIndex;
	pObjFrom->m_linkDoorID[m_fromLinkIndex] = -1;

	if (m_fromOldRoomID != -1)
	{
		CSceneObject *pObj1 = editor->getSceneObjectFromID(m_fromOldRoomID);
		pObj1->m_roomIDLinks[m_fromOldLinkIndex] = -1;
		pObj1->m_linkIndexLinks[m_fromOldLinkIndex] = -1;

		CSceneObject *pOldDoor = editor->getSceneObjectFromID(pObj1->m_linkDoorID[m_fromOldLinkIndex]);
		if (pOldDoor)
		{
			if (!m_pDelCmd1)
			{
				m_pDelCmd1 = new CDeleteCommand(pOldDoor);
			}

			m_pDelCmd1->redo();
		}

		pObj1->m_linkDoorID[m_fromOldLinkIndex] = -1;
	}

	if (m_toId != -1)
	{
		CSceneObject *pObjTo = editor->getSceneObjectFromID(m_toId);
		pObjTo->m_roomIDLinks[m_toLinkIndex] = m_fromId;
		pObjTo->m_linkIndexLinks[m_toLinkIndex] = m_fromLinkIndex;

		if (m_toOldRoomID != -1)
		{
			CSceneObject *pObj2 = editor->getSceneObjectFromID(m_toOldRoomID);
			pObj2->m_roomIDLinks[m_toOldLinkIndex] = -1;
			pObj2->m_linkIndexLinks[m_toOldLinkIndex] = -1;

			CSceneObject *pOldDoor = editor->getSceneObjectFromID(pObj2->m_linkDoorID[m_toOldLinkIndex]);
			if (pOldDoor)
			{
				if (!m_pDelCmd2)
				{
					m_pDelCmd2 = new CDeleteCommand(pOldDoor);
				}

				m_pDelCmd2->redo();
			}

			pObj2->m_linkDoorID[m_toOldLinkIndex] = -1;
		}

		editor->setSelectedNode(0);
		CSceneObject *pObjDoor = editor->createGameObject(editor->getGameObjectIndexFromGameType("Door"), -1);
		stringc name = "LinkNode";
		name += m_fromLinkIndex;
		ISceneNode *pNode = editor->GetLinkNodeFromName(pObjFrom->m_SceneNode, name);
		pObjDoor->m_SceneNode->setPosition(pNode->getAbsolutePosition());
		matrix4 mat = pNode->getAbsoluteTransformation();
		pObjDoor->m_SceneNode->setRelativeTransformation(mat);

		pObjDoor->m_UserData->setAttribute("^Room0^Geometry", pObjFrom->m_SceneNode->getID());
		pObjDoor->m_UserData->setAttribute("^Room1^Geometry", pObjTo->m_SceneNode->getID());
		pObjDoor->InitAttributes();

		pObjFrom->m_linkDoorID[m_fromLinkIndex] = pObjDoor->m_SceneNode->getID();
		pObjTo->m_linkDoorID[m_toLinkIndex] = pObjDoor->m_SceneNode->getID();
	}

	editor->RecalculateCollisions();
}

void CLinkRoomCommand::undo ()
{
	if (m_fromOldRoomID == m_toId && m_fromOldLinkIndex == m_toLinkIndex) 
	{
		return;
	}

	CSceneObject *pObjFrom = editor->getSceneObjectFromID(m_fromId);
	
	if (pObjFrom->m_linkDoorID[m_fromLinkIndex] != -1)
	{
		CSceneObject *pOldDoor = editor->getSceneObjectFromID(pObjFrom->m_linkDoorID[m_fromLinkIndex]);
		CDeleteCommand *delCmd = new CDeleteCommand(pOldDoor);
		delCmd->redo();
		delCmd->drop();
	}

	pObjFrom->m_roomIDLinks[m_fromLinkIndex] = m_fromOldRoomID;
	pObjFrom->m_linkIndexLinks[m_fromLinkIndex] = m_fromOldLinkIndex;
	pObjFrom->m_linkDoorID[m_fromLinkIndex] = m_fromOldDoorID;

	if (m_fromOldRoomID != -1)
	{
		CSceneObject *pObj1 = editor->getSceneObjectFromID(m_fromOldRoomID);
		pObj1->m_roomIDLinks[m_fromOldLinkIndex] = m_fromId;
		pObj1->m_linkIndexLinks[m_fromOldLinkIndex] = m_fromLinkIndex;
		pObj1->m_linkDoorID[m_fromOldLinkIndex] = m_fromOldDoorID;
	}

	if (m_toId != -1)
	{
		CSceneObject *pObjTo = editor->getSceneObjectFromID(m_toId);
		pObjTo->m_roomIDLinks[m_toLinkIndex] = m_toOldRoomID;
		pObjTo->m_linkIndexLinks[m_toLinkIndex] = m_toOldLinkIndex;
		pObjTo->m_linkDoorID[m_toLinkIndex] = m_toOldDoorID;

		if (m_toOldRoomID != -1)
		{
			CSceneObject *pObj2 = editor->getSceneObjectFromID(m_toOldRoomID);
			pObj2->m_roomIDLinks[m_toOldLinkIndex] = m_toId;
			pObj2->m_linkIndexLinks[m_toOldLinkIndex] = m_toLinkIndex;
			pObj2->m_linkDoorID[m_toOldLinkIndex] = m_toOldDoorID;
		}
	}

	if (m_pDelCmd1) m_pDelCmd1->undo();
	if (m_pDelCmd2) m_pDelCmd2->undo();

	editor->RecalculateCollisions();
}
